﻿using System;
using System.Net;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using TravelWallet.Types;
using System.Collections;
using System.Collections.Generic;

namespace TravelWallet
{
    public class ViewModel
    {
        private IStorageModel storageModel;

        private List<Program> programs;

        public List<Program> Programs
        {
            get { return programs; }
            set { programs = value; }
        }

        private ObservableCollection<string> airlineProgramNames;

        public ObservableCollection<string> AirlineProgramNames
        {
            get { return airlineProgramNames; }
            set { airlineProgramNames = value; }
        }
        private ObservableCollection<string> hotelProgramNames;

        public ObservableCollection<string> HotelProgramNames
        {
            get { return hotelProgramNames; }
            set { hotelProgramNames = value; }
        }
        private ObservableCollection<string> carRentalProgramNames;

        public ObservableCollection<string> CarRentalProgramNames
        {
            get { return carRentalProgramNames; }
            set { carRentalProgramNames = value; }
        }

        private ObservableCollection<string> categoryNames;

        public ObservableCollection<string> CategoryNames
        {
            get { return categoryNames; }
            set { categoryNames = value; }
        }

        private ObservableCollection<string> airlineName;

        public ObservableCollection<string> AirlineName
        {
            get { return airlineName; }
            set { airlineName = value; }
        }
        private ObservableCollection<string> hotelNames;

        public ObservableCollection<string> HotelNames
        {
            get { return hotelNames; }
            set { hotelNames = value; }
        }
        private ObservableCollection<string> rentalNames;

        public ObservableCollection<string> RentalNames
        {
            get { return rentalNames; }
            set { rentalNames = value; }
        }

        private ObservableCollection<WalletItem> airlineItems;

        public ObservableCollection<WalletItem> AirlineItems
        {
            get { return airlineItems; }
            set { airlineItems = value; }
        }
        private ObservableCollection<WalletItem> hotelItems;

        public ObservableCollection<WalletItem> HotelItems
        {
            get { return hotelItems; }
            set { hotelItems = value; }
        }
        private ObservableCollection<WalletItem> rentalItems;

        public ObservableCollection<WalletItem> RentalItems
        {
            get { return rentalItems; }
            set { rentalItems = value; }
        }

        public ViewModel(IStorageModel storageModel)
        {
            this.storageModel = storageModel;
            this.airlineItems = new ObservableCollection<WalletItem>();
            this.hotelItems = new ObservableCollection<WalletItem>();
            this.rentalItems = new ObservableCollection<WalletItem>();
            this.hotelNames = new ObservableCollection<string>();
            this.rentalNames = new ObservableCollection<string>();
            this.airlineName = new ObservableCollection<string>();
            this.programs = new List<Program>();
            this.categoryNames = new ObservableCollection<string>();
            this.hotelProgramNames = new ObservableCollection<string>();
            this.airlineProgramNames = new ObservableCollection<string>();
            this.carRentalProgramNames = new ObservableCollection<string>();

            this.CategoryNames.Add("Airlines");
            this.CategoryNames.Add("Hotels");
            this.CategoryNames.Add("Car Rentals");

            RefreshViewModel();
        }




        internal Program AddProgram(string name, string programName, ProgramCategory category)
        {
            Program program = storageModel.AddProgram(name, programName, category);

            //add the new program to the view model cache
            if (category == ProgramCategory.Airlines)
            {
                airlineName.Add(program.Name);
                if (!airlineProgramNames.Contains(program.ProgramName))
                {
                    airlineProgramNames.Add(program.ProgramName);
                    
                }
               
            }
            else if (category == ProgramCategory.CarRentals)
            {
                rentalNames.Add(program.Name);
                if (!carRentalProgramNames.Contains(program.ProgramName))
                {
                    carRentalProgramNames.Add(program.ProgramName);
                }
            }
            else if (category == ProgramCategory.Hotels)
            {
                hotelNames.Add(program.Name);
                if (!hotelProgramNames.Contains(program.ProgramName))
                {
                    hotelProgramNames.Add(program.ProgramName);
                }
            }

            this.programs.Add(program);
            return program;
        }

        private void RefreshViewModel()
        {
            List<WalletItem> userItems = storageModel.GetWalletItems(App.UserID);


            foreach (WalletItem item in userItems)
            {
                if (item.Category == ProgramCategory.Airlines)
                {
                    this.airlineItems.Add(item);
                }
                else if (item.Category == ProgramCategory.CarRentals)
                {
                    this.rentalItems.Add(item);
                }
                else if (item.Category == ProgramCategory.Hotels)
                {
                    this.hotelItems.Add(item);
                }
            }

            List<Program> programs = storageModel.GetPrograms().OrderBy(e => e.Name).ToList();

            foreach (Program program in programs)
            {
                if (program.Category == ProgramCategory.Airlines)
                {
                    airlineName.Add(program.Name);
                }
                else if (program.Category == ProgramCategory.CarRentals)
                {
                    rentalNames.Add(program.Name);
                }
                else if (program.Category == ProgramCategory.Hotels)
                {
                    hotelNames.Add(program.Name);
                }
            }

            this.programs = programs;

            List<string> airlineProgramList = new List<string>();

            programs.ForEach((e) =>
            {
                if (e.Category == ProgramCategory.Airlines && !airlineProgramList.Contains(e.ProgramName))
                {
                    airlineProgramList.Add(e.ProgramName);
                }
            });

            List<string> hotelProgramList = new List<string>();
            programs.ForEach((e) =>
            {
                if (e.Category == ProgramCategory.Hotels && !hotelProgramList.Contains(e.ProgramName))
                {
                    hotelProgramList.Add(e.ProgramName);
                }
            });

            List<string> rentalProgramList = new List<string>();
            programs.ForEach((e) =>
            {
                if (e.Category == ProgramCategory.CarRentals && !rentalProgramList.Contains(e.ProgramName))
                {
                    rentalProgramList.Add(e.ProgramName);
                }
            });


            airlineProgramList.ToList().ForEach(i => AirlineProgramNames.Add(i));
            hotelProgramList.ToList().ForEach(i => HotelProgramNames.Add(i));
            rentalProgramList.ToList().ForEach(i => CarRentalProgramNames.Add(i));
        }

        public void Close()
        {
            this.storageModel.Close();
        }

        public void AddItemToWallet(WalletItem newItem)
        {
            long newID = storageModel.AddWalletItem(newItem);
            if (newItem.Category == ProgramCategory.Airlines)
            {
                airlineItems.Add(newItem);
            }
            else if (newItem.Category == ProgramCategory.CarRentals)
            {
                rentalItems.Add(newItem);
            }
            else
            {
                hotelItems.Add(newItem);
            }

        }

        public void DeleteItemFromWallet(WalletItem itemToDelete)
        {
            storageModel.DeleteWalletItem(itemToDelete.ID);
            if (itemToDelete.Category == ProgramCategory.Airlines)
            {
                airlineItems.Remove(itemToDelete);
            }
            else if (itemToDelete.Category == ProgramCategory.CarRentals)
            {
                rentalItems.Remove(itemToDelete);

            }
            else
            {
                hotelItems.Remove(itemToDelete);

            }
        }

        public void EditItemInWallet(WalletItem itemToEdit)
        {
            storageModel.EditWalletItem(itemToEdit.ID, itemToEdit);

            int airlineIndex = airlineItems.IndexOf(itemToEdit);
            int rentalIndex = rentalItems.IndexOf(itemToEdit);
            int hotelIndex = hotelItems.IndexOf(itemToEdit);

            if (airlineIndex != -1 && itemToEdit.Category != ProgramCategory.Airlines)
            {
                airlineItems.Remove(itemToEdit);

                if (itemToEdit.Category == ProgramCategory.CarRentals)
                {
                    rentalItems.Add(itemToEdit);
                }
                else if (itemToEdit.Category == ProgramCategory.Hotels)
                {
                    hotelItems.Add(itemToEdit);
                }
            }

            if (rentalIndex != -1 && itemToEdit.Category != ProgramCategory.CarRentals)
            {
                rentalItems.Remove(itemToEdit);

                if (itemToEdit.Category == ProgramCategory.Airlines)
                {
                    airlineItems.Add(itemToEdit);
                }
                else if (itemToEdit.Category == ProgramCategory.Hotels)
                {
                    hotelItems.Add(itemToEdit);
                }
            }

            if (hotelIndex != -1 && itemToEdit.Category != ProgramCategory.Hotels)
            {
                hotelItems.Remove(itemToEdit);

                if (itemToEdit.Category == ProgramCategory.Airlines)
                {
                    airlineItems.Add(itemToEdit);
                }
                else if (itemToEdit.Category == ProgramCategory.CarRentals)
                {
                    rentalItems.Add(itemToEdit);
                }
            }
        }

        public WalletItem GetWalletItem(long itemID)
        {
            WalletItem retVal = null;

            var a = from i in airlineItems
                    where i.ID == itemID
                    select i;

            if (a != null && a.Count() > 0)
            {
                return a.First<WalletItem>();
            }

            var b = from i in hotelItems
                    where i.ID == itemID
                    select i;

            if (b != null && b.Count() > 0)
            {
                return b.First<WalletItem>();
            }

            var c = from i in rentalItems
                    where i.ID == itemID
                    select i;

            if (c != null && c.Count() > 0)
            {
                return c.First<WalletItem>();
            }

            return retVal;
        }
        internal bool DoesNameExist(string name)
        {
            bool retVal = false;

            var a = from p in programs
                    where p.Name == name
                    select p;

            if (a != null && a.Count() > 0)
            {
                retVal = true;
            }
            return retVal;
        }

        internal Program GetProgramByName(string name)
        {
            Program retVal = null;

            var a = from p in programs
                    where p.Name == name
                    select p;

            if (a != null && a.Count() == 1)
            {
                retVal = a.First<Program>();
            }
            else
            {
                throw new Exception(string.Format("ViewModel.GetProgramByName: Cannot find program with name {0}", name));
            }

            return retVal;
        }


        internal List<Program> GetProgramsByProgramName(string name)
        {
            List<Program> retVal = null;

            var a = from p in programs
                    where p.ProgramName == name
                    select p;

            if (a != null)
            {
                retVal = a.ToList<Program>();
            }
            else
            {
                throw new Exception(string.Format("ViewModel.GetProgramsByProgramName: Cannot find program with name {0}", name));
            }

            return retVal;
        }


        public int WalletItemsCount()
        {
            List<WalletItem> userItems = storageModel.GetWalletItems(App.UserID);

            return userItems.Count;
        }





    }
}
